home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / spooltoexternal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-08  |  10.6 KB  |  387 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        10/29/92    update to a11            a11
  15. SJF        06/08/92    update to a8            a8
  16. SJF        02/15/92    first working version    a4.5
  17. SJF        10/16/91    initial coding            a3
  18.  
  19. ---------------------------------------------------------------------*/
  20.  
  21. #ifndef __TYPES__
  22. #include <Types.h>
  23. #endif
  24.  
  25. #ifndef __OCE__
  26. #include <OCE.h>
  27. #endif
  28.  
  29. #ifndef __OCEMAIL__
  30. #include <OCEMail.h>
  31. #endif
  32.  
  33. #include <string.h>
  34.  
  35. #include "const.h"
  36. #include "gwerrors.h"
  37. #include "mytypes.h"
  38. #include "globals.h"
  39. #include "utils.h"
  40. #include "spoolsystem.h"
  41. #include "gatewaystuff.h"
  42. #include "smtp.protocol.h"
  43. #include "convertaddress.h"
  44. #include "parser.h"
  45. #include "network.h"
  46.  
  47. #include "spooltoexternal.h"
  48.  
  49. #define    kMaxMsgSize    64000
  50. #define    kBCCBlockSize 2048
  51.  
  52. #define    kFromHeader    "From: "
  53. #define    kToHeader    "To: "
  54. #define    kCCHeader    "Cc: "
  55. #define    kBCCHeader    "Bcc: "
  56. #define    kSubjectHeader "Subject: "
  57. #define    kAddressDelimiter ", "
  58.  
  59. OSErr SpoolToExternalGW(FSSpec *spoolSpec,SlotSpec *slotSpec)
  60. {
  61.     unsigned long smtpServerAddress;
  62.     OSErr err;
  63.     char tmpString[256];
  64.     char bccBlock[256];
  65.     char fromAddr[256];
  66.     char *messageHeader;
  67.     unsigned long tmpLen;
  68.     RString tmpRString;
  69.     char packedRecip[kMaxRecipSize];
  70.     short recipIndex;
  71.     Boolean hasRecipient;
  72.     
  73.     err = InitRemoteNetStuff();
  74.     if (err!=noErr)
  75.         return err;
  76.  
  77.     // allocate memory
  78.     
  79.     messageHeader = (char *)NewPtrChk(kMaxMsgSize);
  80.     if (MemError()!=noErr) {
  81.         return BailOnSend(MemError(),nil);
  82.     }
  83.     messageHeader[0] = 0;
  84.         
  85.     // get IP address of SMTP server
  86.     
  87.     err = ConvertStringToAddr(slotSpec->specInfo.smtpServer,&smtpServerAddress);
  88.     if (err!=noErr) {
  89.         return BailOnSend(kInvalidSMTPServer,messageHeader);
  90.     }
  91.         
  92.     // build from address (from POP account)
  93.     
  94.     strcpy(fromAddr,slotSpec->dirIdentity.userName);
  95.     strcat(fromAddr,"@");
  96.     strcat(fromAddr,slotSpec->specInfo.popServer);
  97.     strcpy(messageHeader,kFromHeader);
  98.     strcat(messageHeader,fromAddr);
  99.     strcat(messageHeader,kCRStr);
  100.  
  101.     // build to address
  102.     
  103.     hasRecipient = false;
  104.     strcat(messageHeader,kToHeader);
  105.     for (err=noErr,recipIndex=0; err==noErr; recipIndex++) {
  106.         tmpLen = kMaxRecipSize;
  107.         err = GetFromSpool(spoolSpec,kToType,kAddrCreator,recipIndex,(Ptr)packedRecip,&tmpLen,0);
  108.         if (err==noErr) {
  109.             if (TranslateAddress((OCEPackedRecipient *)packedRecip,tmpString)) {
  110.                 strcat(messageHeader,tmpString);
  111.                 strcat(messageHeader,kAddressDelimiter);
  112.                 hasRecipient = true;
  113.             }
  114.         }
  115.     }
  116.     if (hasRecipient) {
  117.         messageHeader[strlen(messageHeader)-strlen(kAddressDelimiter)] = 0;
  118.         strcat(messageHeader,kCRStr);
  119.     }
  120.     else {
  121.         messageHeader[strlen(messageHeader)-strlen(kToHeader)] = 0;
  122.     }
  123.  
  124.     // build cc address
  125.     
  126.     hasRecipient = false;
  127.     strcat(messageHeader,kCCHeader);
  128.     for (err=noErr,recipIndex=0; err==noErr; recipIndex++) {
  129.         tmpLen = kMaxRecipSize;
  130.         err = GetFromSpool(spoolSpec,kCCType,kAddrCreator,recipIndex,(Ptr)packedRecip,&tmpLen,0);
  131.         if (err==noErr) {
  132.             if (TranslateAddress((OCEPackedRecipient *)packedRecip,tmpString)) {
  133.                 strcat(messageHeader,tmpString);
  134.                 strcat(messageHeader,kAddressDelimiter);
  135.                 hasRecipient = true;
  136.             }
  137.         }
  138.     }
  139.     if (hasRecipient) {
  140.         messageHeader[strlen(messageHeader)-strlen(kAddressDelimiter)] = 0;
  141.         strcat(messageHeader,kCRStr);
  142.     }
  143.     else {
  144.         messageHeader[strlen(messageHeader)-strlen(kCCHeader)] = 0;
  145.     }
  146.     
  147.     // build bcc address (and store in separate string)
  148.     
  149.     hasRecipient = false;
  150.     strcpy(bccBlock,kBCCHeader);
  151.     for (err=noErr,recipIndex=0; err==noErr; recipIndex++) {
  152.         tmpLen = kMaxRecipSize;
  153.         err = GetFromSpool(spoolSpec,kBCCType,kAddrCreator,recipIndex,(Ptr)packedRecip,&tmpLen,0);
  154.         if (err==noErr) {
  155.             if (TranslateAddress((OCEPackedRecipient *)packedRecip,tmpString)) {
  156.                 strcat(bccBlock,tmpString);
  157.                 strcat(bccBlock,kAddressDelimiter);
  158.                 hasRecipient = true;
  159.             }
  160.         }
  161.     }
  162.     if (hasRecipient) {
  163.         messageHeader[strlen(messageHeader)-strlen(kAddressDelimiter)] = 0;
  164.         strcat(bccBlock,kCRStr);
  165.     }
  166.  
  167.     // build subject
  168.         
  169.     strcat(messageHeader,kSubjectHeader);
  170.     tmpLen = sizeof(RString);
  171.     err = GetFromSpool(spoolSpec,kSubjectType,kAttribCreator,0,(Ptr)&tmpRString,&tmpLen,0);
  172.     if (err==noErr) {
  173.         r2cString(&tmpRString,tmpString);
  174.     }
  175.     else
  176.         strcpy(tmpString,"<none>");
  177.     strcat(messageHeader,tmpString);
  178.     strcat(messageHeader,kCRStr);
  179.     strcat(messageHeader,kCRStr);
  180.  
  181.     // spool message content from AOCE blocks into a single raw text block
  182.     
  183.     err = SpoolBodyFromAOCEToRaw(spoolSpec);
  184.     if (err!=noErr)
  185.         return err;
  186.     
  187.     err = SendSMTP(messageHeader,spoolSpec,bccBlock,fromAddr,smtpServerAddress);
  188.     if (err!=noErr) {
  189.         return BailOnSend(kInvalidSMTPServer,messageHeader);
  190.     }
  191.     
  192.     DisposPtrChk(messageHeader);
  193.     return noErr;
  194. }
  195.  
  196.  
  197. OSErr BailOnSend(OSErr err,Ptr messageBlock)
  198. {
  199.     if (messageBlock)
  200.         DisposPtrChk(messageBlock);
  201.  
  202.     return err;
  203. }
  204.  
  205.  
  206. Boolean TranslateAddress(OCEPackedRecipient *pRecip,char *unixRecip)
  207. {
  208.     OCERecipient rcpt;
  209.     RecordID entitySpecifier;
  210.     OSType recipType;
  211.     RString recipRStr;
  212.     
  213.     OCEUnpackDSSpec((PackedDSSpec*)pRecip,&rcpt,&entitySpecifier);
  214.     recipType = rcpt.extensionType;
  215.     switch (recipType) {
  216.         case kPopAddrType:
  217.             BlockMove(rcpt.extensionValue,&recipRStr,rcpt.extensionSize);    // should probably do some range check
  218.             r2cString(&recipRStr,unixRecip);
  219.             break;
  220.         default: // punt on string representation of aoce addresses for now
  221.             return false;
  222.             break;
  223.     }
  224.     return true;
  225. }
  226.  
  227.  
  228. /* translates a message from AOCE blocks into one large text block for sending over SMTP */
  229.  
  230. OSErr SpoolBodyFromAOCEToRaw(FSSpec *spoolSpec)
  231. {
  232.     OSErr err;
  233.     Ptr bodyBuffer;
  234.     unsigned long blockIndex,contentTypeIndex,rawContentLength,bufferLen;
  235.     char *lfBuffer,*removeTerm;
  236.     OSType contentTypes[kNumContentTypes] = {kTextContent,kPictContent,kSoundContent,
  237.                                             kStyledTextContent,kMovieContent};
  238.     
  239.     bodyBuffer = NewPtrChk(kMaxBufferSize);
  240.     if (MemError()!=noErr)
  241.         return MemError();
  242.     
  243.     // index through all of the blocks, looking for each content type at each index
  244.     // continue until we don't find any content at a particular index
  245.     
  246.     rawContentLength = 0;
  247.  
  248.     for (blockIndex=0,err=noErr; err==noErr; blockIndex++) {
  249.         err = -1;
  250.         for (contentTypeIndex=0; (err!=noErr) && (contentTypeIndex<kNumContentTypes); contentTypeIndex++) {
  251.             err = GetSpoolLength(spoolSpec,contentTypes[contentTypeIndex],kContentCreator,blockIndex,&bufferLen);
  252.             if (err==noErr) {
  253.                 switch (contentTypes[contentTypeIndex]) {
  254.                     case kTextContent:
  255.                         AddTextContent(spoolSpec,blockIndex,bodyBuffer,kMaxBufferSize,&rawContentLength);
  256.                         break;
  257.                     case kPictContent:
  258.                         AddPictContent(spoolSpec,blockIndex,bodyBuffer,kMaxBufferSize,&rawContentLength);
  259.                         break;
  260.                     case kSoundContent:
  261.                         AddSoundContent(spoolSpec,blockIndex,bodyBuffer,kMaxBufferSize,&rawContentLength);
  262.                         break;
  263.                     case kStyledTextContent:
  264.                         AddStyledTextContent(spoolSpec,blockIndex,bodyBuffer,kMaxBufferSize,&rawContentLength);
  265.                         break;
  266.                     case kMovieContent:
  267.                         AddMovieContent(spoolSpec,blockIndex,bodyBuffer,kMaxBufferSize,&rawContentLength);
  268.                         break;
  269.                 }
  270.             }
  271.         }
  272.     }
  273.     if (err==kNoData)
  274.         err = noErr;
  275.         
  276.     DisposPtrChk(bodyBuffer);
  277.     
  278.     return err;
  279. }
  280.  
  281.  
  282. OSErr AddTextContent(FSSpec *spoolSpec,unsigned long blockIndex,Ptr bodyBuffer,
  283.                         unsigned long bufferLength,unsigned long *rawContentLength)
  284. {
  285.     OSErr err,err2;
  286.     unsigned long startOffset,dataLength;
  287.     char *lfBuffer,*removeTerm;
  288.     
  289.     startOffset = 0;
  290.     do {
  291.         dataLength = bufferLength-1;    // leave room for trailing null
  292.         err = GetFromSpool(spoolSpec,kTextContent,kContentCreator,blockIndex,bodyBuffer,
  293.                             &dataLength,startOffset);
  294.         if ((err==noErr)||(err==kMoreData)) {
  295.             bodyBuffer[dataLength] = '\0';
  296.             AddLF(bodyBuffer,&lfBuffer);    // allocates lfBuffer ptr
  297.             
  298.             removeTerm = lfBuffer;
  299.             do {
  300.                 removeTerm = strstr(removeTerm,kMessageTerminator);
  301.                 if (removeTerm)
  302.                     removeTerm[2] = ',';    // substitute all CRLF.CRLF with CRLF,CRLF since this is msg. terminator
  303.             } while (removeTerm);
  304.             
  305.             if (*rawContentLength==0)
  306.                 err2 = SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,lfBuffer,strlen(lfBuffer));
  307.             else
  308.                 err2 = AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,lfBuffer,strlen(lfBuffer));
  309.             if (err2==noErr) {
  310.                 startOffset += dataLength;
  311.                 *rawContentLength += strlen(lfBuffer);
  312.             }
  313.             DisposPtrChk((Ptr)lfBuffer);
  314.         }
  315.     } while ((err2==noErr) && (err==kMoreData));
  316.     
  317.     if (err==noErr)
  318.         err = err2;
  319.         
  320.     return err;
  321. }
  322.  
  323.  
  324. OSErr AddPictContent(FSSpec *spoolSpec,unsigned long blockIndex,Ptr bodyBuffer,
  325.                         unsigned long bufferLength,unsigned long *rawContentLength)
  326. {
  327.     OSErr err;
  328.     char *notSupported = "\015\012\015\012[ picture omitted ]\015\012\015\012";
  329.     
  330.     if (*rawContentLength==0)
  331.         err = SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  332.     else
  333.         err = AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  334.     if (err==noErr)
  335.         *rawContentLength += strlen(notSupported);
  336.     return err;
  337. }
  338.  
  339.  
  340. OSErr AddSoundContent(FSSpec *spoolSpec,unsigned long blockIndex,Ptr bodyBuffer,
  341.                         unsigned long bufferLength,unsigned long *rawContentLength)
  342. {
  343.     OSErr err;
  344.     char *notSupported = "\015\012\015\012[ sound omitted ]\015\012\015\012";
  345.     
  346.     if (*rawContentLength==0)
  347.         err = SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  348.     else
  349.         err = AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  350.     if (err==noErr)
  351.         *rawContentLength += strlen(notSupported);
  352.     return err;
  353. }
  354.  
  355.  
  356. OSErr AddStyledTextContent(FSSpec *spoolSpec,unsigned long blockIndex,Ptr bodyBuffer,
  357.                         unsigned long bufferLength,unsigned long *rawContentLength)
  358. {
  359.     OSErr err;
  360.     char *notSupported = "\015\012\015\012[ styled text omitted ]\015\012\015\012";
  361.     
  362.     if (*rawContentLength==0)
  363.         err = SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  364.     else
  365.         err = AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  366.     if (err==noErr)
  367.         *rawContentLength += strlen(notSupported);
  368.     return err;
  369. }
  370.  
  371.  
  372. OSErr AddMovieContent(FSSpec *spoolSpec,unsigned long blockIndex,Ptr bodyBuffer,
  373.                         unsigned long bufferLength,unsigned long *rawContentLength)
  374. {
  375.     OSErr err;
  376.     char *notSupported = "\015\012\015\012[ movie omitted ]\015\012\015\012";
  377.     
  378.     if (*rawContentLength==0)
  379.         err = SpoolToFile(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  380.     else
  381.         err = AppendToSpool(spoolSpec,kRawContentType,kRawContentCreator,0,notSupported,strlen(notSupported));
  382.     if (err==noErr)
  383.         *rawContentLength += strlen(notSupported);
  384.     return err;
  385. }
  386.  
  387.